package com.huawei.experiencereuse.localmodel;

import android.content.Context;
import android.content.res.AssetManager;
import android.util.Log;

import com.huawei.experiencereuse.utils.ModelUtility;
import com.huawei.experiencereuse.utils.ImageProcessor;


public class LocalModelAgent {

    private static LocalModelAgent instance;
    private static final String TAG = LocalModelAgent.class.getSimpleName();
    private static final float PIC_SIMILAR_THRESHOLD = 0.71f;  // 打车场景可以使用0.91
    private static final float WORD_MATCH_PIC_THRESHOLD = 0.24f;

    private LocalModelAgent() {
    }

    public static LocalModelAgent getInstance() {
        if (instance == null) {
            instance = new LocalModelAgent();
        }
        return instance;
    }

    private void initResources(AssetManager assetManager, String targetDirPath) {
        String amSrcDirRelativePath = "models/";
        String[] resources = {
                "bert62m_npu_input32.omc",
                "vit86m_with_sim_768.omc",
                "vocab.txt"
        };

        // Init resource
        for (String resource : resources) {
            Log.d(TAG, "onCreate: " + resource);
            // invalid judge
            if (!ModelUtility.isResourcesExist(resource, targetDirPath)) {
                Log.d(TAG, "onCreate: " + "开始资源拷贝");
                ModelUtility.copyResourcesToAppDir(assetManager, amSrcDirRelativePath, targetDirPath, resource);
            }
        }
    }

    public void initModel(AssetManager assetManager, String targetDirPath) {
        initResources(assetManager, targetDirPath);

        Log.d(TAG, "模型路径: " + targetDirPath);
        NativeManager.modelExecutorInit(targetDirPath);
        Log.d(TAG, "initModel success");

    }

    public void deinitModel() {
        NativeManager.modelExecutorDeinit();
    }

    private float[] processVit(String picPath) {
        Log.d(TAG, "processVit: " + picPath);
        float[] imageData = ImageProcessor.processImageToFloatArrayForVit(picPath);

        return NativeManager.modelExecutorProcessVit(imageData);
    }

    private float[] processBert(String text) {
        Log.d(TAG, "processBert: " + text);
        return NativeManager.modelExecutorProcessBert(text);
    }

    private float cosSimilarize(float[] vit0, float[] vit1) {
        Log.i(TAG, "vit0.length=" + vit0.length + "vit1.length=" + vit1.length);
        if (vit0 == null || vit1 == null || vit0.length != vit1.length) {
            throw new IllegalArgumentException("Vectors must be non-null and of equal length");
        }

        float dotProduct = 0.0f;
        float norm0 = 0.0f;
        float norm1 = 0.0f;

        for (int i = 0; i < vit0.length; i++) {
            dotProduct += vit0[i] * vit1[i];
            norm0 += vit0[i] * vit0[i];
            norm1 += vit1[i] * vit1[i];
        }

        float denominator = (float) (Math.sqrt(norm0) * Math.sqrt(norm1));
        return denominator == 0 ? 0 : (dotProduct / denominator);
    }
    public boolean isPicSimilar(String picPath0, String picPath1) {
        float[] picVit0 = processVit(picPath0);
        float[] picVit1 = processVit(picPath1);

        float cosSimilar = cosSimilarize(picVit0, picVit1);
        Log.d(TAG, "cosSimilar: " + cosSimilar);
        return (cosSimilar > PIC_SIMILAR_THRESHOLD);
    }

    public boolean isTextMatchPic(String picPath, String text) {
        float[] picVitOut = processVit(picPath);
        float[] textBertOut = processBert(text);

        float cosSimilar = cosSimilarize(picVitOut, textBertOut);
        Log.d(TAG, "cosSimilar: " + cosSimilar);
        return (cosSimilar > WORD_MATCH_PIC_THRESHOLD);
    }
}
